#include "App.h"

using namespace TUMAR::MarkerTracking;
using namespace TUMAR::Render;
using namespace TUMAR::CountryRoads;

namespace TUMAR { namespace App {
	int App::Run(int argc, char* argv[])
	{
		// init render system
		RenderSystem renderSystem;
		renderSystem.Init(argc, argv);

		// configure marker ids here
		MarkerEnvironment env;
		env.BoardPositionMarkerId    = 4648;
		env.BoardScaleMarkerId       = 626;
		env.UserMarkerRoadStraightId = 1680;
		env.UserMarkerRoadCurveId    = 7236;

		// configure game here
		Game game;
		game.TileLockTimeout = 2.0;
		game.MovementStartTimeout = 25.0;
		game.MovementTimeout = 5.0;

		// configure game board here
		GameBoard board(7, 7);
		GameController controller(&game, &board, &env);

		// allocate
		CameraVideoSource video;
		VideoSourceTimerCallbackAdapter videoTimer(&video);
		
		Marker::RealSize = 1;
		MarkerTracker tracker;
		VideoRenderer videoRenderer;
		UIRenderer uiRenderer;
		GameBoardRenderer boardRenderer;

		// connect events
		videoTimer.ImageCaptured.connect(1, boost::bind(&VideoRenderer::OnImageCaptured, &videoRenderer, _1));
		videoTimer.ImageCaptured.connect(2, boost::bind(&MarkerTracker::OnImageCaptured, &tracker, _1));

		tracker.MarkersFound.connect(1, boost::bind(&GameController::OnMarkersFound, &controller, _1));

		renderSystem.KeyPressed.connect(1, boost::bind(&GameController::OnKeyPressed, &controller, _1));

		controller.GameUpdated.connect(1, boost::bind(&GameBoardRenderer::OnGameUpdated, &boardRenderer, _1, _2, _3));
		//controller.GameUpdated.connect(1, boost::bind(&UIRenderer::OnGameUpdated, &uiRenderer, _1));
				
		// add renderers in the order they should render
		renderSystem.AddRenderer(&videoRenderer);
		renderSystem.AddRenderer(&boardRenderer);
		renderSystem.AddRenderer(&uiRenderer);
		
		// TODO: replace this with some in-game GUI
		std::cout << "Press [SPACE] to generate game board content." << std::endl;
		std::cout << "Press [ENTER] to start game." << std::endl;
		std::cout << std::endl;

		// start timers
		videoTimer.Start();
		
		// start main loop
		renderSystem.StartRenderLoop();

		return 0;
	}
}}